package com.andova.egl

import android.graphics.SurfaceTexture
import android.opengl.EGL14
import android.opengl.EGLConfig
import android.opengl.EGLSurface
import android.os.Handler
import android.os.HandlerThread
import android.os.Looper
import android.os.Message
import android.view.TextureView
import com.andova.glcamera.MSG_EGL_HELPER_WHAT_DELAY_TASK
import com.andova.glcamera.MSG_EGL_HELPER_WHAT_INIT
import com.andova.glcamera.MSG_EGL_HELPER_WHAT_RENDER

class TextureEglHelper(name: String = "TextureEglHelper") : HandlerThread(name), SurfaceTexture.OnFrameAvailableListener, EglTextureCallback {
    private var mTaskHandler: Handler? = null
    private var mTextureView: TextureView? = null

    /**
     * 显示设备
     */
    private var mEGLDisplay = EGL14.EGL_NO_DISPLAY

    /**
     * EGL上下文
     */
    private var mEGLContext = EGL14.EGL_NO_CONTEXT

    /**
     * 描述帧缓冲区配置参数
     */
    private val configs = arrayOfNulls<EGLConfig>(1)

    /**
     * EGL绘图表面
     */
    private var mEglSurface: EGLSurface? = null

    /**
     * 自定义的SurfaceTexture
     * 用来接受Camera数据作二次处理
     */
    private var mTextureSurface: SurfaceTexture? = null
    private var mTextureRender: OnTextureListener? = null

    fun initEgl(textureView: TextureView, render: OnTextureListener, width: Int, height: Int) {
        mTextureView = textureView
        mTextureRender = render
        start()
        mTaskHandler = TaskHandler(looper ?: throw NullPointerException("handler thread looper is null!"))
        mTaskHandler?.sendMessage(Message.obtain(mTaskHandler, MSG_EGL_HELPER_WHAT_INIT, width, height))
    }

    private fun initEGLContext(width: Int, height: Int, clientVersion: Int = 3) {
        mEGLDisplay = EGL14.eglGetDisplay(EGL14.EGL_DEFAULT_DISPLAY)//获取显示设备
        if (mEGLDisplay == EGL14.EGL_NO_DISPLAY) throw RuntimeException("eglGetDisplay error: " + EGL14.eglGetError())
        val version = IntArray(2)//存放EGL版本号
        version[0] = 3
        if (!EGL14.eglInitialize(mEGLDisplay, version, 0, version, 1)) throw RuntimeException("eglInitialize error: " + EGL14.eglGetError())
        val attributes = intArrayOf(
            EGL14.EGL_BUFFER_SIZE,
            32,
            EGL14.EGL_RED_SIZE,
            8,
            EGL14.EGL_GREEN_SIZE,
            8,
            EGL14.EGL_BLUE_SIZE,
            8,
            EGL14.EGL_ALPHA_SIZE,
            8,
            EGL14.EGL_RENDERABLE_TYPE,
            4,
            EGL14.EGL_SURFACE_TYPE,
            EGL14.EGL_WINDOW_BIT,
            EGL14.EGL_NONE
        )//配置列表
        val numConfigs = IntArray(1)
        //EGL选择配置
        if (!EGL14.eglChooseConfig(mEGLDisplay, attributes, 0, configs, 0, configs.size, numConfigs, 0)) throw RuntimeException("eglChooseConfig error: " + EGL14.eglGetError())
        val surfaceTexture = mTextureView?.surfaceTexture ?: throw RuntimeException("surfaceTexture is null")
        val surfaceAttributes = intArrayOf(EGL14.EGL_NONE)//创建EGL显示窗口
        mEglSurface = EGL14.eglCreateWindowSurface(mEGLDisplay, configs[0], surfaceTexture, surfaceAttributes, 0)
        val contextAttributes = intArrayOf(EGL14.EGL_CONTEXT_CLIENT_VERSION, clientVersion, EGL14.EGL_NONE)//创建上下文环境
        mEGLContext = EGL14.eglCreateContext(mEGLDisplay, configs[0], EGL14.EGL_NO_CONTEXT, contextAttributes, 0)
        if (mEGLDisplay == EGL14.EGL_NO_DISPLAY || mEGLContext == EGL14.EGL_NO_CONTEXT) throw RuntimeException("eglCreateContext fail error: " + EGL14.eglGetError())
        if (!EGL14.eglMakeCurrent(mEGLDisplay, mEglSurface, mEglSurface, mEGLContext)) throw RuntimeException("eglMakeCurrent error: " + EGL14.eglGetError())
        mTextureRender?.onAvailable(width, height)
    }

    private fun drawFrame() {
        mTextureRender?.run {
            onTextureFrame(mTextureSurface)
            EGL14.eglSwapBuffers(mEGLDisplay, mEglSurface)
        }
    }

    fun sendMessageDelayed(what: Int, delayMillis: Long) {
        mTaskHandler?.sendMessageDelayed(Message.obtain(mTaskHandler, MSG_EGL_HELPER_WHAT_DELAY_TASK, what, 0), delayMillis)
    }

    fun onSurfaceSizeChanged(width: Int, height: Int) {
        mTextureRender?.onSizeChanged(width, height)
    }

    override fun onFrameAvailable(surfaceTexture: SurfaceTexture?) {
        mTaskHandler?.sendEmptyMessage(MSG_EGL_HELPER_WHAT_RENDER)
    }

    override fun onLoadTexture(textureId: Int): SurfaceTexture? {
        if (mTextureSurface == null) {
            mTextureSurface = SurfaceTexture(textureId)
            mTextureSurface?.setOnFrameAvailableListener(this)
        }
        return mTextureSurface
    }

    override fun onResumeTexture() {
        TODO("Not yet implemented")
    }

    fun onSurfaceDestroy() {
        quitSafely()
        mTaskHandler?.removeCallbacksAndMessages(null)

        EGL14.eglMakeCurrent(mEGLDisplay, EGL14.EGL_NO_SURFACE, EGL14.EGL_NO_SURFACE, EGL14.EGL_NO_CONTEXT)
        EGL14.eglDestroyContext(mEGLDisplay, mEGLContext)
        EGL14.eglDestroySurface(mEGLDisplay, mEglSurface)
        EGL14.eglReleaseThread()
        EGL14.eglTerminate(mEGLDisplay)

        mTextureRender?.onDestroyed(mTextureSurface)
    }

    private inner class TaskHandler(looper: Looper) : Handler(looper) {
        override fun handleMessage(msg: Message) {
            when (msg.what) {
                MSG_EGL_HELPER_WHAT_INIT -> initEGLContext(msg.arg1, msg.arg2)
                MSG_EGL_HELPER_WHAT_RENDER -> drawFrame()
                MSG_EGL_HELPER_WHAT_DELAY_TASK -> mTextureRender?.onDelayTask(msg.arg1)
            }
        }
    }
}